{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Lumped Elements Circuits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, we construct various network from basic lumped elements (resistor, capacitor, inductor), with the 'classic' and the `Circuit` approach. Generally the `Circuit` approach is more verbose than the 'classic' way for building a circuit. However, as the circuit complexity increases, in particular when components are connected in parallel, the `Circuit` approach is interesting as it increases the readability of the code. Moreover, `Circuit` object can be plotted using its `plot_graph()` method, which is useful to rapidly control if the circuit is built as expected.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np  # for np.allclose() to check that S-params are similar\n",
    "\n",
    "import skrf as rf\n",
    "\n",
    "rf.stylely()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LC Series Circuit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this section we reproduce a simple equivalent model of a capacitor $C$, as illustrated by the figure below:\n",
    "\n",
    "<img src=\"designer_capacitor_simple.png\" width=\"700\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# reference LC circuit made in Designer\n",
    "LC_designer = rf.Network('designer_capacitor_30_80MHz_simple.s2p')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: manually connecting networks\n",
    "line = rf.media.DefinedGammaZ0(frequency=LC_designer.frequency, z0=50)\n",
    "LC_manual = line.inductor(24e-9) ** line.capacitor(70e-12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: using Circuit builder\n",
    "port1 = rf.Circuit.Port(frequency=LC_designer.frequency, name='port1', z0=50)\n",
    "port2 = rf.Circuit.Port(frequency=LC_designer.frequency, name='port2', z0=50)\n",
    "cap = rf.Circuit.SeriesImpedance(frequency=LC_designer.frequency, name='cap', z0=50,\n",
    "                                 Z=1/(1j*LC_designer.frequency.w*70e-12))\n",
    "ind = rf.Circuit.SeriesImpedance(frequency=LC_designer.frequency, name='ind', z0=50,\n",
    "                                 Z=1j*LC_designer.frequency.w*24e-9)\n",
    "\n",
    "# NB: it is also possible to create 2-port lumped elements like:\n",
    "# line = rf.media.DefinedGammaZ0(frequency=LC_designer.frequency, z0=50)\n",
    "# cap = line.capacitor(70e-12, name='cap')\n",
    "# ind = line.inductor(24e-9, name='ind')\n",
    "\n",
    "connections = [\n",
    "    [(port1, 0), (cap, 0)],\n",
    "    [(cap, 1), (ind, 0)],\n",
    "    [(ind, 1), (port2, 0)]\n",
    "]\n",
    "circuit = rf.Circuit(connections)\n",
    "LC_from_circuit = circuit.network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# testing the equivalence of the results\n",
    "print(np.allclose(LC_designer.s, LC_manual.s))\n",
    "print(np.allclose(LC_designer.s, LC_from_circuit.s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "circuit.plot_graph(network_labels=True, edge_labels=True, port_labels=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A More Advanced Equivalent Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this section we reproduce an equivalent model of a capacitor $C$, as illustrated by the figure below:\n",
    "\n",
    "<img src=\"designer_capacitor_adv.png\" width=\"800\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Reference results from ANSYS Designer\n",
    "LCC_designer = rf.Network('designer_capacitor_30_80MHz_adv.s2p')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: usual way, but this time this is more tedious to deal with connection and port number\n",
    "freq = LCC_designer.frequency\n",
    "line = rf.media.DefinedGammaZ0(frequency=freq, z0=50)\n",
    "elements1 = line.resistor(1e-2) ** line.inductor(24e-9) ** line.capacitor(70e-12)\n",
    "elements2 = line.resistor(20e6)\n",
    "T_in = line.tee()\n",
    "T_out = line.tee()\n",
    "ntw = rf.connect(T_in, 1, elements1, 0)\n",
    "ntw = rf.connect(ntw, 2, elements2, 0)\n",
    "ntw = rf.connect(ntw, 1, T_out, 1)\n",
    "ntw = rf.innerconnect(ntw, 1, 2)\n",
    "LCC_manual = ntw ** line.shunt_capacitor(50e-12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: using Circuit builder\n",
    "freq = LCC_designer.frequency\n",
    "port1 = rf.Circuit.Port(frequency=freq, name='port1', z0=50)\n",
    "port2 = rf.Circuit.Port(frequency=freq, name='port2', z0=50)\n",
    "line = rf.media.DefinedGammaZ0(frequency=freq, z0=50)\n",
    "cap = line.capacitor(70e-12, name='cap')\n",
    "ind = line.inductor(24e-9, name='ind')\n",
    "res_series = line.resistor(1e-2, name='res_series')\n",
    "res_parallel = line.resistor(20e6, name='res_parallel')\n",
    "cap_shunt = line.capacitor(50e-12, name='cap_shunt')\n",
    "ground = rf.Circuit.Ground(frequency=freq, name='ground', z0=50)\n",
    "\n",
    "connections = [\n",
    "    [(port1, 0), (res_series, 0), (res_parallel, 0)],\n",
    "    [(res_series, 1), (cap, 0)],\n",
    "    [(cap, 1), (ind, 0)],\n",
    "    [(ind, 1), (cap_shunt, 0), (res_parallel, 1), (port2, 0)],\n",
    "    [(cap_shunt, 1), (ground, 0)],\n",
    "]\n",
    "circuit = rf.Circuit(connections)\n",
    "LCC_from_circuit = circuit.network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# testing the equivalence of the results\n",
    "print(np.allclose(LCC_designer.s, LCC_manual.s))\n",
    "print(np.allclose(LCC_designer.s, LCC_from_circuit.s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "circuit.plot_graph(network_labels=True, edge_labels=True, port_labels=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pass band filter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below we construct a pass-band filter, from an example given in [Microwaves101](https://www.microwaves101.com/encyclopedias/lumped-element-filter-calculator):"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"designer_bandpass_filter_450_550MHz.png\" width=\"800\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Reference result calculated from Designer\n",
    "passband_designer = rf.Network('designer_bandpass_filter_450_550MHz.s2p')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: the filter by cascading all lumped-elements\n",
    "freq = passband_designer.frequency\n",
    "passband_manual = line.shunt_capacitor(25.406e-12) ** line.shunt_inductor(4.154e-9) ** \\\n",
    "                  line.capacitor(2.419e-12) ** line.inductor(43.636e-9) ** \\\n",
    "                  line.shunt_capacitor(25.406e-12) ** line.shunt_inductor(4.154e-9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scikit-rf: the filter with the Circuit builder\n",
    "freq = passband_designer.frequency\n",
    "line = rf.media.DefinedGammaZ0(frequency=freq)\n",
    "C1 = line.capacitor(25.406e-12, name='C1')\n",
    "C2 = line.capacitor(2.419e-12, name='C2')\n",
    "C3 = line.capacitor(25.406e-12, name='C3')\n",
    "L1 = line.inductor(4.154e-9, name='L1')\n",
    "L2 = line.inductor(43.636e-9, name='L2')\n",
    "L3 = line.inductor(4.154e-9, name='L3')\n",
    "port1 = rf.Circuit.Port(frequency=freq, name='port1', z0=50)\n",
    "port2 = rf.Circuit.Port(frequency=freq, name='port2', z0=50)\n",
    "ground =  rf.Circuit.Ground(frequency=freq, name='ground', z0=50)\n",
    "\n",
    "connections = [\n",
    "    [(port1, 0), (C1, 0), (L1, 0), (C2, 0)],\n",
    "    [(C2, 1), (L2, 0)],\n",
    "    [(L2, 1), (C3, 0), (L3, 0), (port2, 0)],\n",
    "    [(C1, 1), (C3, 1), (L1, 1), (L3, 1), (ground, 0)],\n",
    "]\n",
    "\n",
    "circuit = rf.Circuit(connections)\n",
    "passband_circuit = circuit.network\n",
    "passband_circuit.name = 'Pass-band circuit'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "passband_circuit.plot_s_db(m=0, n=0, lw=2)\n",
    "passband_circuit.plot_s_db(m=1, n=0, lw=2)\n",
    "passband_designer.plot_s_db(m=0, n=0, lw=2, ls='-.')\n",
    "passband_designer.plot_s_db(m=1, n=0, lw=2, ls='-.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "circuit.plot_graph(network_labels=True, port_labels=True, edge_labels=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.6 ('.venv': venv)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  },
  "vscode": {
   "interpreter": {
    "hash": "637c323cf467337602e9974a89cb4d3fc95fac3ef875a73e62754f8e768d8de7"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
